package net.sk.china.front.service.impl.system;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.sk.china.common.config.TalkConfig;
import net.sk.china.common.constants.Constants;
import net.sk.china.common.exception.TalkException;
import net.sk.china.common.model.system.SystemConfig;
import net.sk.china.common.utils.RedisUtil;
import net.sk.china.front.dao.system.SystemConfigDao;
import net.sk.china.front.service.system.SystemConfigService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * SystemConfigServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * // | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * // +----------------------------------------------------------------------
 * // | Copyright (c) 2018-2024 聊来 All rights reserved.
 * // +----------------------------------------------------------------------
 * // | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * // +----------------------------------------------------------------------
 * // | @Author: 聊来 <18970881148@qq.com>
 * // +----------------------------------------------------------------------
 * // | DateTime: 2024/6/3 10:25
 * // +----------------------------------------------------------------------
 */

@Service
public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigDao, SystemConfig> implements SystemConfigService {

    @Resource
    private SystemConfigDao dao;

    private final RedisUtil redisUtil;

    private final TalkConfig talkConfig;

    private static final String REDIS_KEY = Constants.CONFIG_LIST;

    public SystemConfigServiceImpl(RedisUtil redisUtil, TalkConfig talkConfig) {
        this.redisUtil = redisUtil;
        this.talkConfig = talkConfig;
    }



    /**
     * 根据menu name 获取 value
     * @param name menu
     * @return {@code String}
     */
    @Override
    public String getValueByKey(String name) { return get(name); }

    /**
     * 根据 name 获取 value 找不到抛异常
     * @param name menu
     * @return {@code String}
     */
    @Override
    public String getValueByKeyException(String name) {
        String value = get(name);
        if (null == value) {
            throw new TalkException("没有找到"+ name +"数据");
        }
        return value;
    }

    /**
     * 同时获取多个配置
     * @param keys 多个配置key
     * @return {@code List<String>}
     */
    @Override
    public List<String> getValuesByKes(List<String> keys) {
        List<String> result = new ArrayList<>();
        for (String key : keys) {
            result.add(getValueByKey(key));
        }
        return result;
    }

    /**
     * 把数据同步到redis
     * @param name String
     * @return String
     */
    private String get(String name) {
        if (!talkConfig.isAsyncConfig()) {
            //如果配置没有开启
            LambdaQueryWrapper<SystemConfig> query = new LambdaQueryWrapper<>();
            query.eq(SystemConfig::getStatus, false).eq(SystemConfig::getName, name);
            SystemConfig systemConfig = dao.selectOne(query);
            if (ObjectUtil.isNull(systemConfig) || StrUtil.isBlank(systemConfig.getValue())) {
                return "";
            }
            return systemConfig.getValue();
        }
        setRedisByVoList();
        Object data = redisUtil.hmGet(REDIS_KEY, name);
        if (ObjectUtil.isNull(data) || StrUtil.isBlank(data.toString())) {
            //没有找到数据
            return "";
        }
        //去数据库查找，然后写入redis
        return data.toString();
    }

    /**
     * 把数据同步到redis, 此方法适用于redis为空的时候进行一次批量输入
     */
    private void setRedisByVoList() {
        //检测redis是否为空
        Long size = redisUtil.getHashSize(REDIS_KEY);
        if (size > 0 || !talkConfig.isAsyncConfig()) {
            return;
        }

        LambdaQueryWrapper<SystemConfig> query = new LambdaQueryWrapper<>();
        query.eq(SystemConfig::getStatus, false);
        List<SystemConfig> systemConfigList = dao.selectList(query);
        async(systemConfigList);
    }

    /**
     * 把数据同步到redis
     * @param systemConfigList List<SystemConfig> 需要同步的数据
     */
    private void async(List<SystemConfig> systemConfigList) {
        if (!talkConfig.isAsyncConfig()) {
            //如果配置没有开启
            return;
        }
        for (SystemConfig systemConfig : systemConfigList) {
            redisUtil.hmSet(REDIS_KEY, systemConfig.getName(), systemConfig.getValue());
        }
    }

    /**
     * 删除redis的缓存数据
     * @param name String
     */
    private void deleteRedis(String name) {
        if (!talkConfig.isAsyncConfig()) {
            //如果配置没有开启
            return;
        }
        redisUtil.hmDelete(REDIS_KEY, name);
    }
}
